package com.zjw.zy.heart.service.impl;

import com.zjw.zy.heart.wbsocket.socket.WsMessage;
import com.zjw.zy.heart.configuration.TaskPool;
import com.zjw.zy.heart.service.IWechatService;
import com.zjw.zy.heart.userpool.IUserPool;
import com.zjw.zy.heart.utils.LogUtils;
import com.zjw.zy.heart.wbsocket.WsSender;
import com.zjw.zy.heart.wbsocket.IWSConnectHandler;
import com.zjw.zy.heart.wbsocket.IWSMessageHandler;
import com.zjw.zy.heart.wbsocket.WsDispatcher;
import jakarta.websocket.Session;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import java.util.List;


@Service
public class WechatServiceImpl implements IWechatService, IWSMessageHandler, IWSConnectHandler {

    private static final String TAG = "WeChatServiceImpl";
    private JmsMessagingTemplate jmsMessagingTemplate;

    private Queue queue;

    private IUserPool userPool;

    private WsDispatcher dispatcher;

    private RedisTemplate<String, WsMessage> redisCache;

    @Override
    public void onHandleWsMessage(@NonNull WsMessage message) {
        //转发给active-mq
        //jmsMessagingTemplate.convertAndSend(queue, message);
        pushToTargetUser(message);
    }

    @Override
    public boolean onInterceptWsMessage(@NonNull WsMessage message) {
        String info = message.getInfo();
        return info.startsWith(WsMessage.WECHAT_MESSAGE_INFO) || WsMessage.WECHAT_MESSAGE_PULL_INFO.equals(info) || WsMessage.WECHAT_MESSAGE_SYNC_INFO.equals(info);
    }

    @Override
    @Async(TaskPool.CONCURRENT_POOL)
    public void pushToTargetUser(WsMessage message) {
        Session session = userPool.querySession(message.getTo());
        boolean success = WsSender.sendToClient(session, message);
        if (!success) {
            //缓存消息
            String target = message.getTo();
            ListOperations<String, WsMessage> ops = redisCache.opsForList();
            //缓存到redis钟
            ops.rightPush(target, message);
            LogUtils.d(TAG, "cache message " + message);
        } else {
            LogUtils.d(TAG, "push message success " + message);
        }
    }

    @Override
    public void pullByTarget(String username) {
        ListOperations<String, WsMessage> ops = redisCache.opsForList();
        List<WsMessage> wsMessages = ops.range(username, 0, -1);
        LogUtils.d(TAG, "pull message " + username + " cache->");
        if (wsMessages == null || wsMessages.isEmpty()) {
            return;
        }


        Session session = userPool.querySession(username);
        WsMessage pull = WsMessage.obtain(WsMessage.WECHAT_MESSAGE_PULL_INFO);
        pull.setPayload(wsMessages);
        boolean success = WsSender.convertAndSendToClient(session, pull);
        if (success) {
            Boolean delete = redisCache.delete(username);
            LogUtils.d(TAG, "delete cache " + delete);
        }

    }

    @Autowired
    @Qualifier("WechatQueue")
    public void setQueue(Queue queue) {
        this.queue = queue;
    }


    @Autowired
    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        this.jmsMessagingTemplate = new JmsMessagingTemplate(connectionFactory);
    }

    @Autowired
    public void setUserPool(IUserPool userPool) {
        this.userPool = userPool;
    }

    @Autowired
    @Qualifier("wechat-cache")
    public void setRedisCache(RedisTemplate<String, WsMessage> redisCache) {
        this.redisCache = redisCache;
    }


    @Autowired
    public void setDispatcher(WsDispatcher dispatcher) {
        this.dispatcher = dispatcher;
        dispatcher.addWsMessageInterceptor(this);
        dispatcher.addWsConnectInterceptor(this);
    }

    @Override
    public boolean onInterceptOpen(Session session) {
        return true;
    }

    @Override
    public void onHandleOpen(Session session, String username) {
        this.pullByTarget(username);
    }
}
